#Объект Future в контексте asyncio: Объект, представляющий отложенный результат асинхронной операции
###############################
###########
#В каком состоянии находится объект Future сразу после его создания? PENDING (ожидание)
###############################
###########
#Как перевести объект Future в состояние "завершено"? Завершением связанной с ним асинхронной операции
###############################
###########
#Что произойдет при попытке получить результат из объекта Future в состоянии "ожидание"?
#Будет вызвано исключение, так как результат ещё не доступен
#################################
############
#Как отменить выполнение асинхронной операции, связанной с объектом Future? Использованием метода cancel()
##################################
#############
#Что возвращает метод result() объекта Future после успешного завершения асинхронной операции? Результат выполненной асинхронной операции
###################################
#############
#Можно ли использовать объект Future для выполнения асинхронной операции без await? Нет, объект Future предназначен для использования с await
###################################
###############
#Что покажет следующий код?
# import asyncio

# async def set_after(fut, delay, value):
#     await asyncio.sleep(delay)
#     fut.set_result(value)

# async def main():
#     future = asyncio.Future()
#     asyncio.ensure_future(set_after(future, 1, 'done'))
#     result = await future
#     print(result)

# asyncio.run(main())

#Выведет "done"
####################################
# import asyncio

# async def set_future_result(value, delay):
#     print(f"Задача начата. Установка результата '{value}' через {delay} секунд.")
#     await asyncio.sleep(delay)
#     print("Результат установлен.")
#     return value

# async def create_and_use_future():
#     future = asyncio.ensure_future(set_future_result('Успех', 2))
#     if not future.done():
#         print("Состояние Future до выполнения: Ожидание")
#     else:
#         print("Состояние Future до выполнения: Завершено")
#     print("Задача запущена, ожидаем завершения...")
#     await future
#     if future.done():
#         print("Состояние Future после выполнения: Завершено") 
#     else:
#         print("Состояние Future после выполнения: Ожидание")
#     return future.result()



# async def main():
#     result = await create_and_use_future()
#     print("Результат из Future:", result)

# asyncio.run(main())
####################################################################
# import asyncio

# async def async_operation():
#     print("Начало асинхронной операции.")
#     try:
#         await asyncio.sleep(2)
#         print("Асинхронная операция успешно завершилась.")
#     except asyncio.CancelledError:

#         print("Асинхронная операция была отменена в процессе выполнения.")
#         raise asyncio.CancelledError
    
# async def main():
#     print("Главная корутина запущена.")
#     future = asyncio.ensure_future(async_operation())
#     await asyncio.sleep(0.1)
#     print("Попытка отмены Future.")
#     future.cancel()

#     try:
#         result = await future
#         print("Результат Future:", result)
#     except asyncio.CancelledError:
#         print("Обработка исключения: Future был отменен.")

#     if future.cancelled():
#         print("Проверка: Future был отменен.")
#     else:
#         print("Проверка: Future не был отменен.")
#     print("Главная корутина завершена.")

# asyncio.run(main())
#######################################################
# Последовательное выполнение future с зависимостями от других future
# Часто возникает необходимость в последовательном выполнении задач, где результат одной операции служит входными данными 
# для следующей. Реализуйте такой подход с помощью объектов Future и функции ensure_future(). Создайте и запустите
# цепочку асинхронных функций, где каждая последующая функция зависит от результата предыдущей.

import asyncio

async def first_function(x):
    print(f"Выполняется первая функция с аргументом {x}")
    await asyncio.sleep(1)
    result = x + 1
    print(f"Первая функция завершилась с результатом {result}")
    return result


async def second_function(x):
    print(f"Выполняется вторая функция с аргументом {x}")
    await asyncio.sleep(1)
    result  = x * 2
    print(f"Вторая функция завершилась с результатом {result}")
    return result

async def third_function(x):
    print(f"Выполняется третья функция с аргументом {x}")
    await asyncio.sleep(1)
    result  = x + 3
    print(f"Третья функция завершилась с результатом {result}")
    return result

async def fourth_function(x):
    print(f"Выполняется четвертая функция с аргументом {x}")
    await asyncio.sleep(1)
    result  = x ** 2
    print(f"Четвертая функция завершилась с результатом {result}")
    return result

async def main():
    print("Начало цепочки асинхронных вызовов")
    future_1 = asyncio.ensure_future(first_function(1))
    res_1 = await future_1
    future_2 = asyncio.ensure_future(second_function(res_1))
    res_2 = await future_2
    future_3 = asyncio.ensure_future(third_function(res_2))
    res_3 = await future_3
    future_4 = asyncio.ensure_future(fourth_function(res_3))

    final_result = await future_4

    print(f"Конечный результат цепочки вызовов: {final_result}")


asyncio.run(main())

